home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / zcpp_jae.zip / CPP5.C < prev    next >
C/C++ Source or Header  |  1991-05-18  |  24KB  |  948 lines

  1. /*
  2.  
  3.  
  4.  Copyright (C) 1990 Texas Instruments Incorporated.
  5.  
  6.  Permission is granted to any individual or institution to use, copy, modify,
  7.  and distribute this software, provided that this complete copyright and
  8.  permission notice is maintained, intact, in all copies and supporting
  9.  documentation.
  10.  
  11.  Texas Instruments Incorporated provides this software "as is" without
  12.  express or implied warranty.
  13.  
  14.  
  15.  *                C P P 5 . C
  16.  *        E x p r e s s i o n   E v a l u a t i o n
  17.  *
  18.  * Edit History
  19.  * 31-Aug-84    MM    USENET net.sources release
  20.  * 04-Oct-84    MM    __LINE__ and __FILE__ must call ungetstring()
  21.  *            so they work correctly with token concatenation.
  22.  *            Added string formal recognition.
  23.  * 25-Oct-84    MM    "Short-circuit" evaluate #if's so that we
  24.  *            don't print unnecessary error messages for
  25.  *            #if !defined(FOO) && FOO != 0 && 10 / FOO ...
  26.  * 31-Oct-84    ado/MM    Added token concatenation
  27.  *  6-Nov-84    MM    Split from #define stuff, added sizeof stuff
  28.  * 19-Nov-84    ado    #if error returns TRUE for (sigh) compatibility
  29.  * 21-Oct-85    RMS    Rename `token' to `tokenbuf'
  30.  * 23-Oct-85    RMS    Treat undefined symbols as having value zero.
  31.  * 27-Apr-91    gcg     Added support for the void basic type.
  32.  * 18-May-91    dle     Set small model pointers sizes for DOS/OS2.
  33.  */
  34.  
  35. #include    <stdio.h>
  36. #include    <ctype.h>
  37. #include    "cppdef.h"
  38. #include    "cpp.h"
  39.  
  40. /*
  41.  * Evaluate an #if expression.
  42.  */
  43.  
  44. static char    *opname[] = {        /* For debug and error messages    */
  45. "end of expression", "val", "id",
  46.   "+",   "-",  "*",  "/",  "%",
  47.   "<<", ">>",  "&",  "|",  "^",
  48.   "==", "!=",  "<", "<=", ">=",  ">",
  49.   "&&", "||",  "?",  ":",  ",",
  50.   "unary +", "unary -", "~", "!",  "(",  ")", "(none)",
  51. };
  52.  
  53. /*
  54.  * opdope[] has the operator precedence:
  55.  *     Bits
  56.  *      7    Unused (so the value is always positive)
  57.  *    6-2    Precedence (000x .. 017x)
  58.  *    1-0    Binary op. flags:
  59.  *        01    The binop flag should be set/cleared when this op is seen.
  60.  *        10    The new value of the binop flag.
  61.  * Note:  Expected, New binop
  62.  * constant    0    1    Binop, end, or ) should follow constants
  63.  * End of line    1    0    End may not be preceeded by an operator
  64.  * binary    1    0    Binary op follows a value, value follows.
  65.  * unary    0    0    Unary op doesn't follow a value, value follows
  66.  *   (        0    0    Doesn't follow value, value or unop follows
  67.  *   )        1    1    Follows value.  Op follows.
  68.  */
  69.  
  70. static char    opdope[OP_MAX] = {
  71.   0001,                    /* End of expression        */
  72.   0002,                    /* Digit            */
  73.   0000,                    /* Letter (identifier)        */
  74.   0141, 0141, 0151, 0151, 0151,        /* ADD, SUB, MUL, DIV, MOD    */
  75.   0131, 0131, 0101, 0071, 0071,        /* ASL, ASR, AND,  OR, XOR    */
  76.   0111, 0111, 0121, 0121, 0121,    0121,    /*  EQ,  NE,  LT,  LE,  GE,  GT    */
  77.   0061, 0051, 0041, 0041, 0031,        /* ANA, ORO, QUE, COL, CMA    */
  78. /*
  79.  * Unary op's follow
  80.  */
  81.   0160, 0160, 0160, 0160,        /* NEG, PLU, COM, NOT        */
  82.   0170, 0013, 0023,            /* LPA, RPA, END        */
  83. };
  84. /*
  85.  * OP_QUE and OP_RPA have alternate precedences:
  86.  */
  87. #define    OP_RPA_PREC    0013
  88. #define OP_QUE_PREC    0034
  89.  
  90. /*
  91.  * S_ANDOR and S_QUEST signal "short-circuit" boolean evaluation, so that
  92.  *    #if FOO != 0 && 10 / FOO ...
  93.  * doesn't generate an error message.  They are stored in optab.skip.
  94.  */
  95. #define S_ANDOR        2
  96. #define S_QUEST        1
  97.  
  98. typedef struct optab {
  99.     char    op;            /* Operator            */
  100.     char    prec;            /* Its precedence        */
  101.     char    skip;            /* Short-circuit: TRUE to skip    */
  102. } OPTAB;
  103. static int    evalue;            /* Current value from evallex()    */
  104.  
  105. #ifdef    nomacargs
  106. FILE_LOCAL int
  107. isbinary(op)
  108. register int    op;
  109. {
  110.     return (op >= FIRST_BINOP && op <= LAST_BINOP);
  111. }
  112.  
  113. FILE_LOCAL int
  114. isunary(op)
  115. register int    op;
  116. {
  117.     return (op >= FIRST_UNOP && op <= LAST_UNOP);
  118. }
  119. #else
  120. #define    isbinary(op)    (op >= FIRST_BINOP && op <= LAST_BINOP)
  121. #define    isunary(op)    (op >= FIRST_UNOP  && op <= LAST_UNOP)
  122. #endif
  123.  
  124. /*
  125.  * The following definitions are used to specify basic variable sizes.
  126.  */
  127.  
  128. #if (HOST == SYS_OS2)
  129. #define    S_PCHAR        2
  130. #define    S_PSINT        2
  131. #define    S_PINT        2
  132. #define    S_PLINT        2
  133. #define    S_PFLOAT    2
  134. #define    S_PDOUBLE    2
  135. #define    S_PFPTR        2
  136. #define    S_PVOID        2
  137. #endif
  138.  
  139. #ifndef    S_CHAR
  140. #define    S_CHAR        (sizeof (char))
  141. #endif
  142. #ifndef    S_SINT
  143. #define    S_SINT        (sizeof (short int))
  144. #endif
  145. #ifndef    S_INT
  146. #define    S_INT        (sizeof (int))
  147. #endif
  148. #ifndef    S_LINT
  149. #define    S_LINT        (sizeof (long int))
  150. #endif
  151. #ifndef    S_FLOAT
  152. #define    S_FLOAT        (sizeof (float))
  153. #endif
  154. #ifndef    S_DOUBLE
  155. #define    S_DOUBLE    (sizeof (double))
  156. #endif
  157. #ifndef    S_PCHAR
  158. #define    S_PCHAR        (sizeof (char *))
  159. #endif
  160. #ifndef    S_PSINT
  161. #define    S_PSINT        (sizeof (short int *))
  162. #endif
  163. #ifndef    S_PINT
  164. #define    S_PINT        (sizeof (int *))
  165. #endif
  166. #ifndef    S_PLINT
  167. #define    S_PLINT        (sizeof (long int *))
  168. #endif
  169. #ifndef    S_PFLOAT
  170. #define    S_PFLOAT    (sizeof (float *))
  171. #endif
  172. #ifndef    S_PDOUBLE
  173. #define    S_PDOUBLE    (sizeof (double *))
  174. #endif
  175. #ifndef    S_PFPTR
  176. #define S_PFPTR        (sizeof (int (*)()))
  177. #endif
  178. #ifdef VOID_SUPPORT
  179. #ifndef S_PVOID
  180. #define S_PVOID         (sizeof (void *))
  181. #endif
  182. #endif
  183.  
  184. typedef struct types {
  185.     short    type;            /* This is the bit if        */
  186.     char    *name;            /* this is the token word    */
  187. } TYPES;
  188.  
  189. static TYPES basic_types[] = {
  190.     { T_CHAR,    "char",        },
  191.     { T_INT,    "int",        },
  192.     { T_FLOAT,    "float",    },
  193.     { T_DOUBLE,    "double",    },
  194.     { T_SHORT,    "short",    },
  195.     { T_LONG,    "long",        },
  196.     { T_SIGNED,    "signed",    },
  197.     { T_UNSIGNED,    "unsigned",    },
  198. #ifdef VOID_SUPPORT
  199.         { T_VOID,       "void",         },
  200. #endif
  201.     { 0,        NULL,        },    /* Signal end        */
  202. };
  203.  
  204. /*
  205.  * Test_table[] is used to test for illegal combinations.
  206.  */
  207. static short test_table[] = {
  208.     T_FLOAT | T_DOUBLE | T_LONG | T_SHORT,
  209.     T_FLOAT | T_DOUBLE | T_CHAR | T_INT,
  210.     T_FLOAT | T_DOUBLE | T_SIGNED | T_UNSIGNED,
  211.     T_LONG  | T_SHORT  | T_CHAR,
  212.     0                        /* end marker    */
  213. };
  214.  
  215. /*
  216.  * The order of this table is important -- it is also referenced by
  217.  * the command line processor to allow run-time overriding of the
  218.  * built-in size values.  The order must not be changed:
  219.  *    char, short, int, long, float, double (func pointer)
  220.  */
  221. SIZES size_table[] = {
  222.     { T_CHAR,    S_CHAR,        S_PCHAR        },    /* char        */
  223.     { T_SHORT,    S_SINT,        S_PSINT        },    /* short int    */
  224.     { T_INT,    S_INT,        S_PINT        },    /* int        */
  225.     { T_LONG,    S_LINT,        S_PLINT        },    /* long        */
  226.     { T_FLOAT,    S_FLOAT,    S_PFLOAT    },    /* float    */
  227.     { T_DOUBLE,    S_DOUBLE,    S_PDOUBLE    },    /* double    */
  228.     { T_FPTR,    0,        S_PFPTR        },    /* int (*())     */
  229. #ifdef VOID_SUPPORT
  230.     { T_VOID,   0,              S_PVOID         },      /* void *       */
  231. #endif
  232.     { 0,    0,        0        },    /* End of table    */
  233. };
  234.  
  235. int
  236. eval()
  237. /*
  238.  * Evaluate an expression.  Straight-forward operator precedence.
  239.  * This is called from control() on encountering an #if statement.
  240.  * It calls the following routines:
  241.  * evallex    Lexical analyser -- returns the type and value of
  242.  *        the next input token.
  243.  * evaleval    Evaluate the current operator, given the values on
  244.  *        the value stack.  Returns a pointer to the (new)
  245.  *        value stack.
  246.  * For compatiblity with older cpp's, this return returns 1 (TRUE)
  247.  * if a syntax error is detected.
  248.  */
  249. {
  250.     register int    op;        /* Current operator        */
  251.     register int    *valp;        /* -> value vector        */
  252.     register OPTAB    *opp;        /* Operator stack        */
  253.     int        prec;        /* Op precedence        */
  254.     int        binop;        /* Set if binary op. needed    */
  255.     int        op1;        /* Operand from stack        */
  256.     int        skip;        /* For short-circuit testing    */
  257.     int        value[NEXP];    /* Value stack            */
  258.     OPTAB        opstack[NEXP];    /* Operand stack        */
  259.     extern int    *evaleval();    /* Does actual evaluation    */
  260.  
  261.     valp = value;
  262.     opp = opstack;
  263.     opp->op = OP_END;        /* Mark bottom of stack        */
  264.     opp->prec = opdope[OP_END];    /* And its precedence        */
  265.     opp->skip = 0;            /* Not skipping now        */
  266.     binop = 0;
  267. again:    ;
  268. #ifdef    DEBUG_EVAL
  269.     printf("In #if at again: skip = %d, binop = %d, line is: %s",
  270.         opp->skip, binop, infile->bptr);
  271. #endif
  272.     if ((op = evallex(opp->skip)) == OP_SUB && binop == 0)
  273.         op = OP_NEG;            /* Unary minus        */
  274.     else if (op == OP_ADD && binop == 0)
  275.         op = OP_PLU;            /* Unary plus        */
  276.     else if (op == OP_FAIL)
  277.         return (1);                /* Error in evallex    */
  278. #ifdef    DEBUG_EVAL
  279.     printf("op = %s, opdope = %03o, binop = %d, skip = %d\n",
  280.         opname[op], opdope[op], binop, opp->skip);
  281. #endif
  282.     if (op == DIG) {            /* Value?        */
  283.         if (binop != 0) {
  284.         cerror("misplaced constant in #if", NULLST);
  285.         return (1);
  286.         }
  287.         else if (valp >= &value[NEXP-1]) {
  288.         cerror("#if value stack overflow", NULLST);
  289.         return (1);
  290.         }
  291.         else {
  292. #ifdef    DEBUG_EVAL
  293.         printf("pushing %d onto value stack[%d]\n",
  294.             evalue, valp - value);
  295. #endif
  296.         *valp++ = evalue;
  297.         binop = 1;
  298.         }
  299.         goto again;
  300.     }
  301.     else if (op > OP_END) {
  302.         cerror("Illegal #if line", NULLST);
  303.         return (1);
  304.     }
  305.     prec = opdope[op];
  306.     if (binop != (prec & 1)) {
  307.         cerror("Operator %s in incorrect context", opname[op]);
  308.         return (1);
  309.     }
  310.     binop = (prec & 2) >> 1;
  311.     for (;;) {
  312. #ifdef    DEBUG_EVAL
  313.         printf("op %s, prec %d., stacked op %s, prec %d, skip %d\n",
  314.         opname[op], prec, opname[opp->op], opp->prec, opp->skip);
  315. #endif
  316.         if (prec > opp->prec) {
  317.         if (op == OP_LPA)
  318.             prec = OP_RPA_PREC;
  319.         else if (op == OP_QUE)
  320.             prec = OP_QUE_PREC;
  321.         op1 = opp->skip;        /* Save skip for test    */
  322.         /*
  323.          * Push operator onto op. stack.
  324.          */
  325.         opp++;
  326.         if (opp >= &opstack[NEXP]) {
  327.             cerror("expression stack overflow at op \"%s\"",
  328.             opname[op]);
  329.             return (1);
  330.         }
  331.         opp->op = op;
  332.         opp->prec = prec;
  333.         skip = (valp>value) && (valp[-1] != 0);/*Short-circuit tester*/
  334.         /*
  335.          * Do the short-circuit stuff here.  Short-circuiting
  336.          * stops automagically when operators are evaluated.
  337.          */
  338.         if ((op == OP_ANA && !skip)
  339.          || (op == OP_ORO && skip))
  340.             opp->skip = S_ANDOR;    /* And/or skip starts    */
  341.         else if (op == OP_QUE)        /* Start of ?: operator    */
  342.             opp->skip = (op1 & S_ANDOR) | ((!skip) ? S_QUEST : 0);
  343.         else if (op == OP_COL) {    /* : inverts S_QUEST    */
  344.             opp->skip = (op1 & S_ANDOR)
  345.                   | (((op1 & S_QUEST) != 0) ? 0 : S_QUEST);
  346.         }
  347.         else {                /* Other ops leave    */
  348.             opp->skip = op1;        /*  skipping unchanged.    */
  349.         }
  350. #ifdef    DEBUG_EVAL
  351.         printf("stacking %s, valp[-1] == %d at %s",
  352.             opname[op], valp[-1], infile->bptr);
  353.         dumpstack(opstack, opp, value, valp);
  354. #endif
  355.         goto again;
  356.         }
  357.         /*
  358.          * Pop operator from op. stack and evaluate it.
  359.          * End of stack and '(' are specials.
  360.          */
  361.         skip = opp->skip;            /* Remember skip value    */
  362.         switch ((op1 = opp->op)) {        /* Look at stacked op    */
  363.         case OP_END:            /* Stack end marker    */
  364.         if (op == OP_EOE)
  365.             return (valp[-1]);        /* Finished ok.        */
  366.         goto again;            /* Read another op.    */
  367.  
  368.         case OP_LPA:            /* ( on stack        */
  369.         if (op != OP_RPA) {        /* Matches ) on input    */
  370.             cerror("unbalanced paren's, op is \"%s\"", opname[op]);
  371.             return (1);
  372.         }
  373.         opp--;                /* Unstack it        */
  374.         /* goto again;            -- Fall through        */
  375.  
  376.         case OP_QUE:
  377.         goto again;            /* Evaluate true expr.    */
  378.  
  379.         case OP_COL:            /* : on stack.        */
  380.         opp--;                /* Unstack :        */
  381.         if (opp->op != OP_QUE) {    /* Matches ? on stack?    */
  382.             cerror("Misplaced '?' or ':', previous operator is %s",
  383.             opname[opp->op]);
  384.             return (1);
  385.         }
  386.         /*
  387.          * Evaluate op1.
  388.          */
  389.         default:                /* Others:        */
  390.         opp--;                /* Unstack the operator    */
  391. #ifdef    DEBUG_EVAL
  392.         printf("Stack before evaluation of %s\n", opname[op1]);
  393.         dumpstack(opstack, opp, value, valp);
  394. #endif
  395.         valp = evaleval(valp, op1, skip);
  396. #ifdef    DEBUG_EVAL
  397.         printf("Stack after evaluation\n");
  398.         dumpstack(opstack, opp, value, valp);
  399. #endif
  400.         }                    /* op1 switch end    */
  401.     }                    /* Stack unwind loop    */
  402. }
  403.  
  404. FILE_LOCAL int
  405. evallex(skip)
  406. int        skip;        /* TRUE if short-circuit evaluation    */
  407. /*
  408.  * Return next eval operator or value.  Called from eval().  It
  409.  * calls a special-purpose routines for 'char' strings and
  410.  * numeric values:
  411.  * evalchar    called to evaluate 'x'
  412.  * evalnum    called to evaluate numbers.
  413.  */
  414. {
  415.     register int    c, c1, t;
  416.  
  417. again:                      /* Collect the token    */
  418.     c = skipws();
  419.     if ((c = macroid(c)) == EOF_CHAR || c == '\n') {
  420.       unget();
  421.       return (OP_EOE);        /* End of expression    */
  422.     }
  423.     t = type[c];
  424.     if (t == INV) {                /* Total nonsense    */
  425.         if (!skip) {
  426.         if (isascii(c) && isprint(c))
  427.             cierror("illegal character '%c' in #if", c);
  428.         else
  429.             cierror("illegal character (%d decimal) in #if", c);
  430.         }
  431.         return (OP_FAIL);
  432.     }
  433.     else if (t == QUO) {            /* ' or "        */
  434.         if (c == '\'') {            /* Character constant    */
  435.         evalue = evalchar(skip);    /* Somewhat messy    */
  436. #ifdef    DEBUG_EVAL
  437.         printf("evalchar returns %d.\n", evalue);
  438. #endif
  439.         return (DIG);            /* Return a value    */
  440.         }
  441.         cerror("Can't use a string in an #if", NULLST);
  442.         return (OP_FAIL);
  443.     }
  444.     else if (t == LET) {            /* ID must be a macro    */
  445.         if (streq(tokenbuf, "defined")) {    /* Or defined name    */
  446.         c1 = c = skipws();
  447.         if (c == '(')            /* Allow defined(name)    */
  448.             c = skipws();
  449.         if (type[c] == LET) {
  450.             evalue = (lookid(c) != NULL);
  451.             if (c1 != '('        /* Need to balance    */
  452.              || skipws() == ')')    /* Did we balance?    */
  453.             return (DIG);        /* Parsed ok        */
  454.         }
  455.         cerror("Bad #if ... defined() syntax", NULLST);
  456.         return (OP_FAIL);
  457.         }
  458.         else if (streq(tokenbuf, "sizeof"))    /* New sizeof hackery    */
  459.         return (dosizeof());        /* Gets own routine    */
  460.         evalue = 0;
  461.         return (DIG);
  462.     }
  463.     else if (t == DIG) {            /* Numbers are harder    */
  464.         evalue = evalnum(c);
  465. #ifdef    DEBUG_EVAL
  466.         printf("evalnum returns %d.\n", evalue);
  467. #endif
  468.     }
  469.     else if (t == SPA) {
  470.       goto again;
  471.     }
  472.     else if (strchr("=<>&|\\!", c) != NULL) {
  473.         /*
  474.          * Process a possible multi-byte lexeme.
  475.          */
  476.         c1 = cget();            /* Peek at next char    */
  477.         switch (c) {
  478.         case '!':
  479.         if (c1 == '=')
  480.             return (OP_NE);
  481.         break;
  482.  
  483.         case '=':
  484.         if (c1 != '=') {        /* Can't say a=b in #if    */
  485.             unget();
  486.             cerror("= not allowed in #if", NULLST);
  487.             return (OP_FAIL);
  488.         }
  489.         return (OP_EQ);
  490.  
  491.         case '>':
  492.         case '<':
  493.         if (c1 == c)
  494.             return ((c == '<') ? OP_ASL : OP_ASR);
  495.         else if (c1 == '=')
  496.             return ((c == '<') ? OP_LE  : OP_GE);
  497.         break;
  498.  
  499.         case '|':
  500.         case '&':
  501.         if (c1 == c)
  502.             return ((c == '|') ? OP_ORO : OP_ANA);
  503.         break;
  504.  
  505.         case '\\':
  506.         if (c1 == '\n')            /* Multi-line if    */
  507.             goto again;
  508.         cerror("Unexpected \\ in #if", NULLST);
  509.         return (OP_FAIL);
  510.         }
  511.         unget();
  512.     }
  513.     return (t);
  514. }
  515.  
  516. FILE_LOCAL int
  517. dosizeof()
  518. /*
  519.  * Process the sizeof (basic type) operation in an #if string.
  520.  * Sets evalue to the size and returns
  521.  *    DIG        success
  522.  *    OP_FAIL        bad parse or something.
  523.  */
  524. {
  525.     register int    c;
  526.     register TYPES    *tp;
  527.     register SIZES    *sizp;
  528.     register short    *testp;
  529.     short        typecode;
  530.  
  531.     if ((c = skipws()) != '(')
  532.         goto nogood;
  533.     /*
  534.      * Scan off the tokens.
  535.      */
  536.     typecode = 0;
  537.     while ((c = skipws())) {
  538.         if ((c = macroid(c)) == EOF_CHAR || c == '\n')
  539.         goto nogood;            /* End of line is a bug    */
  540.         else if (c == '(') {        /* thing (*)() func ptr    */
  541.         if (skipws() == '*'
  542.          && skipws() == ')') {        /* We found (*)        */
  543.             if (skipws() != '(')    /* Let () be optional    */
  544.             unget();
  545.             else if (skipws() != ')')
  546.             goto nogood;
  547.             typecode |= T_FPTR;        /* Function pointer    */
  548.         }
  549.         else {                /* Junk is a bug    */
  550.             goto nogood;
  551.         }
  552.         }
  553.         else if (type[c] != LET)        /* Exit if not a type    */
  554.         break;
  555.         else {                    /* Maybe combine tokens    */
  556.         /*
  557.          * Look for this unexpandable token in basic_types.
  558.          * The code accepts "int long" as well as "long int"
  559.          * which is a minor bug as bugs go (and one shared with
  560.          * a lot of C compilers).
  561.          */
  562.         for (tp = basic_types; tp->name != NULLST; tp++) {
  563.             if (streq(tokenbuf, tp->name))
  564.             break;
  565.         }
  566.         if (tp->name == NULLST) {
  567.             cerror("#if sizeof, unknown type \"%s\"", tokenbuf);
  568.             return (OP_FAIL);
  569.         }
  570.         typecode |= tp->type;        /* Or in the type bit    */
  571.         }
  572.     }
  573.     /*
  574.      * We are at the end of the type scan.  Chew off '*' if necessary.
  575.      */
  576.     if (c == '*') {
  577.         typecode |= T_PTR;
  578.         c = skipws();
  579.     }
  580.     if (c == ')') {                /* Last syntax check    */
  581.         for (testp = test_table; *testp != 0; testp++) {
  582.         if (!bittest(typecode & *testp)) {
  583.             cerror("#if ... sizeof: illegal type combination", NULLST);
  584.             return (OP_FAIL);
  585.         }
  586.         }
  587. #ifdef VOID_SUPPORT
  588.         if (typecode == T_VOID) {
  589.             cerror ("#if sizeof() error: cannot take sizeof(void)", NULLST);
  590.             return (OP_FAIL);
  591.         }
  592. #endif
  593.         /*
  594.          * We assume that all function pointers are the same size:
  595.          *        sizeof (int (*)()) == sizeof (float (*)())
  596.          * We assume that signed and unsigned don't change the size:
  597.          *        sizeof (signed int) == (sizeof unsigned int)
  598.          */
  599.         if ((typecode & T_FPTR) != 0)    /* Function pointer    */
  600.         typecode = T_FPTR | T_PTR;
  601.         else {                /* Var or var * datum    */
  602.         typecode &= ~(T_SIGNED | T_UNSIGNED);
  603.         if ((typecode & (T_SHORT | T_LONG)) != 0)
  604.             typecode &= ~T_INT;
  605.         }
  606.         if ((typecode & ~T_PTR) == 0) {
  607.         cerror("#if sizeof() error, no type specified", NULLST);
  608.         return (OP_FAIL);
  609.         }
  610.         /*
  611.          * Exactly one bit (and possibly T_PTR) may be set.
  612.          */
  613.         for (sizp = size_table; sizp->bits != 0; sizp++) {
  614.         if ((typecode & ~T_PTR) == sizp->bits) {
  615.             evalue = ((typecode & T_PTR) != 0)
  616.             ? sizp->psize : sizp->size;
  617.             return (DIG);
  618.         }
  619.         }                    /* We shouldn't fail    */
  620.         cierror("#if ... sizeof: bug, unknown type code 0x%x", typecode);
  621.         return (OP_FAIL);
  622.     }
  623.  
  624. nogood:    unget();
  625.     cerror("#if ... sizeof() syntax error", NULLST);
  626.     return (OP_FAIL);
  627. }
  628.  
  629. FILE_LOCAL int
  630. bittest(value)
  631. /*
  632.  * TRUE if value is zero or exactly one bit is set in value.
  633.  */
  634. {
  635. #if (4096 & ~(-4096)) == 0
  636.     return ((value & ~(-value)) == 0);
  637. #else
  638.     /*
  639.      * Do it the hard way (for non 2's complement machines)
  640.      */
  641.     return (value == 0 || value ^ (value - 1) == (value * 2 - 1));
  642. #endif
  643. }
  644.  
  645. FILE_LOCAL int
  646. evalnum(c)
  647. register int    c;
  648. /*
  649.  * Expand number for #if lexical analysis.  Note: evalnum recognizes
  650.  * the unsigned suffix, but only returns a signed int value.
  651.  */
  652. {
  653.     register int    value;
  654.     register int    base;
  655.     register int    c1;
  656.  
  657.     if (c != '0')
  658.         base = 10;
  659.     else if ((c = cget()) == 'x' || c == 'X') {
  660.         base = 16;
  661.         c = cget();
  662.     }
  663.     else base = 8;
  664.     value = 0;
  665.     for (;;) {
  666.         c1 = c;
  667.         if (isascii(c) && isupper(c1))
  668.         c1 = tolower(c1);
  669.         if (c1 >= 'a' && c1 <= 'f')
  670.         c1 -= ('a' - 10);
  671.         else c1 -= '0';
  672.         if (c1 < 0 || c1 >= base)
  673.         break;
  674.         value *= base;
  675.         value += c1;
  676.         c = cget();
  677.     }
  678.     if (c == 'u' || c == 'U')    /* Unsigned nonsense        */
  679.         c = cget();
  680.     unget();
  681.     return (value);
  682. }
  683.  
  684. FILE_LOCAL int
  685. evalchar(skip)
  686. int        skip;        /* TRUE if short-circuit evaluation    */
  687. /*
  688.  * Get a character constant
  689.  */
  690. {
  691.     register int    c;
  692.     register int    value;
  693.     register int    count;
  694.  
  695.     instring = TRUE;
  696.     if ((c = cget()) == '\\') {
  697.         switch ((c = cget())) {
  698.         case 'a':                /* New in Standard    */
  699. #if ('a' == '\a' || '\a' == ALERT)
  700.         value = ALERT;            /* Use predefined value    */
  701. #else
  702.         value = '\a';            /* Use compiler's value    */
  703. #endif
  704.         break;
  705.  
  706.         case 'b':
  707.         value = '\b';
  708.         break;
  709.  
  710.         case 'f':
  711.         value = '\f';
  712.         break;
  713.  
  714.         case 'n':
  715.         value = '\n';
  716.         break;
  717.  
  718.         case 'r':
  719.         value = '\r';
  720.         break;
  721.  
  722.         case 't':
  723.         value = '\t';
  724.         break;
  725.  
  726.         case 'v':                /* New in Standard    */
  727. #if ('v' == '\v' || '\v' == VT)
  728.         value = VT;            /* Use predefined value    */
  729. #else
  730.         value = '\v';            /* Use compiler's value    */
  731. #endif
  732.         break;
  733.  
  734.         case 'x':                /* '\xFF'        */
  735.         count = 3;
  736.         value = 0;
  737.         while ((((c = get()) >= '0' && c <= '9')
  738.              || (c >= 'a' && c <= 'f')
  739.              || (c >= 'A' && c <= 'F'))
  740.             && (--count >= 0)) {
  741.             value *= 16;
  742.             value += (c >= '0' && c <= '9') ?
  743.               (c - '0') : ((c & 0xF) + 9);
  744.         }
  745.         unget();
  746.         break;
  747.  
  748.         default:
  749.         if (c >= '0' && c <= '7') {
  750.             count = 3;
  751.             value = 0;
  752.             while (c >= '0' && c <= '7' && --count >= 0) {
  753.             value *= 8;
  754.             value += (c - '0');
  755.             c = get();
  756.             }
  757.             unget();
  758.         }
  759.         else value = c;
  760.         break;
  761.         }
  762.     }
  763.     else if (c == '\'')
  764.         value = 0;
  765.     else value = c;
  766.     /*
  767.      * We warn on multi-byte constants and try to hack
  768.      * (big|little)endian machines.
  769.      */
  770. #if BIG_ENDIAN
  771.     count = 0;
  772. #endif
  773.     while ((c = get()) != '\'' && c != EOF_CHAR && c != '\n') {
  774.         if (!skip)
  775.         ciwarn("multi-byte constant '%c' isn't portable", c);
  776. #if BIG_ENDIAN
  777.         count += BITS_CHAR;
  778.         value += (c << count);
  779. #else
  780.         value <<= BITS_CHAR;
  781.         value += c;
  782. #endif
  783.     }
  784.     instring = FALSE;
  785.     return (value);
  786. }
  787.  
  788. FILE_LOCAL int *
  789. evaleval(valp, op, skip)
  790. register int    *valp;
  791. int        op;
  792. int        skip;        /* TRUE if short-circuit evaluation    */
  793. /*
  794.  * Apply the argument operator to the data on the value stack.
  795.  * One or two values are popped from the value stack and the result
  796.  * is pushed onto the value stack.
  797.  *
  798.  * OP_COL is a special case.
  799.  *
  800.  * evaleval() returns the new pointer to the top of the value stack.
  801.  */
  802. {
  803.     register int    v1, v2;
  804.  
  805.     if (isbinary(op))
  806.         v2 = *--valp;
  807.     v1 = *--valp;
  808. #ifdef    DEBUG_EVAL
  809.     printf("%s op %s", (isbinary(op)) ? "binary" : "unary",
  810.         opname[op]);
  811.     if (isbinary(op))
  812.         printf(", v2 = %d.", v2);
  813.     printf(", v1 = %d.\n", v1);
  814. #endif
  815.     switch (op) {
  816.     case OP_EOE:
  817.          break;
  818.  
  819.     case OP_ADD:
  820.         v1 += v2;
  821.         break;
  822.  
  823.     case OP_SUB:
  824.         v1 -= v2;
  825.         break;
  826.  
  827.     case OP_MUL:
  828.         v1 *= v2;
  829.         break;
  830.  
  831.     case OP_DIV:
  832.     case OP_MOD:
  833.         if (v2 == 0) {
  834.         if (!skip) {
  835.             cwarn("%s by zero in #if, zero result assumed",
  836.             (op == OP_DIV) ? "divide" : "mod");
  837.         }
  838.         v1 = 0;
  839.         }
  840.         else if (op == OP_DIV)
  841.         v1 /= v2;
  842.         else
  843.         v1 %= v2;
  844.         break;
  845.  
  846.     case OP_ASL:
  847.         v1 <<= v2;
  848.         break;
  849.  
  850.     case OP_ASR:
  851.         v1 >>= v2;
  852.         break;
  853.  
  854.     case OP_AND:
  855.         v1 &= v2;
  856.         break;
  857.  
  858.     case OP_OR:
  859.         v1 |= v2;
  860.         break;
  861.  
  862.     case OP_XOR:
  863.         v1 ^= v2;
  864.         break;
  865.  
  866.     case OP_EQ:
  867.         v1 = (v1 == v2);
  868.         break;
  869.  
  870.     case OP_NE:
  871.         v1 = (v1 != v2);
  872.         break;
  873.  
  874.     case OP_LT:
  875.         v1 = (v1 < v2);
  876.         break;
  877.  
  878.     case OP_LE:
  879.         v1 = (v1 <= v2);
  880.         break;
  881.  
  882.     case OP_GE:
  883.         v1 = (v1 >= v2);
  884.         break;
  885.  
  886.     case OP_GT:
  887.         v1 = (v1 > v2);
  888.         break;
  889.  
  890.     case OP_ANA:
  891.         v1 = (v1 && v2);
  892.         break;
  893.  
  894.     case OP_ORO:
  895.         v1 = (v1 || v2);
  896.         break;
  897.  
  898.     case OP_COL:
  899.         /*
  900.          * v1 has the "true" value, v2 the "false" value.
  901.          * The top of the value stack has the test.
  902.          */
  903.         v1 = (*--valp) ? v1 : v2;
  904.         break;
  905.  
  906.     case OP_NEG:
  907.         v1 = (-v1);
  908.         break;
  909.  
  910.     case OP_PLU:
  911.         break;
  912.  
  913.     case OP_COM:
  914.         v1 = ~v1;
  915.         break;
  916.  
  917.     case OP_NOT:
  918.         v1 = !v1;
  919.         break;
  920.  
  921.     default:
  922.         cierror("#if bug, operand = %d.", op);
  923.         v1 = 0;
  924.     }
  925.     *valp++ = v1;
  926.     return (valp);
  927. }
  928.  
  929. #ifdef    DEBUG_EVAL
  930. dumpstack(opstack, opp, value, valp)
  931. OPTAB        opstack[NEXP];    /* Operand stack        */
  932. register OPTAB    *opp;        /* Operator stack        */
  933. int        value[NEXP];    /* Value stack            */
  934. register int    *valp;        /* -> value vector        */
  935. {
  936.     printf("index op prec skip name -- op stack at %s", infile->bptr);
  937.     while (opp > opstack) {
  938.         printf(" [%2d] %2d  %03o    %d %s\n", opp - opstack,
  939.         opp->op, opp->prec, opp->skip, opname[opp->op]);
  940.         opp--;
  941.     }
  942.     while (--valp >= value) {
  943.         printf("value[%d] = %d\n", (valp - value), *valp);
  944.     }
  945. }
  946. #endif
  947.  
  948.